package com.calm.editor.point;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;

import javax.annotation.Resource;

import org.springframework.aop.support.AopUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

import com.calm.editor.api.CacheHandler;
import com.calm.editor.servlet.Event;
import com.calm.editor.servlet.Parameter;
@Service
public class DefaultCacheHandler implements CacheHandler<Parameter,CacheBean> {
	@Resource
	private ApplicationContext context;
	
	@Override
	public CacheBean handler(Parameter key) throws Exception {
		CacheBean resultBean=new CacheBean();
		Object bean = context.getBean(key.getBean());
		resultBean.setTargetBean(bean);
		boolean aopProxy = AopUtils.isAopProxy(bean);
		Class<?> targetClass;
		Class<?> clazz;
		if(aopProxy){
			targetClass = AopUtils.getTargetClass(bean);
			
		}else{
			targetClass = bean.getClass();
		}
		clazz= bean.getClass();
		Method[] methods = targetClass.getMethods();
		Method targetMethod = null;
		String methodName = null;
		String method = key.getMethod();
		for(Method m:methods){
			String name = m.getName();
			if(name.equals(method)){
				targetMethod = m;
				methodName = name;
				break;
			}
		}
		
		Method[] methodTemps = clazz.getMethods();
		Method targetMethodTemps = null;
		for(Method m:methodTemps){
			String name = m.getName();
			if(name.equals(method)){
				targetMethodTemps = m;
				break;
			}
		}
		
		if(targetMethod==null){
			throw new NoSuchMethodException(method);
		}
		resultBean.setTargetMethod(targetMethodTemps);
		Class<?>[] parameterTypes;
		Method mostSpecificMethod;
		if(aopProxy){
			mostSpecificMethod = AopUtils.getMostSpecificMethod(targetMethod, targetClass);
			parameterTypes = mostSpecificMethod.getParameterTypes();
		}else{
			parameterTypes = targetMethod.getParameterTypes();
			mostSpecificMethod = targetMethod;
		}
		resultBean.setParameterTypes(parameterTypes);
		Event annotation = mostSpecificMethod.getAnnotation(Event.class);
		List<String> asList;
		if(annotation==null){
			asList = Arrays.asList(methodName);
		}else{
			String[] value = annotation.value();
			asList = Arrays.asList(value);
		}
		resultBean.setEvents(asList);
		
		return resultBean;
	}
}
